package top.util.concurrent.atomic;

import sun.misc.Unsafe;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntUnaryOperator;

/**
 * @author He Kuntao
 * @since 2025/6/12 10:47
 */
public class FAtomicInteger extends Number {

    private static final Unsafe unsafe = Unsafe.getUnsafe();

    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset(FAtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }

    private volatile int value;

    public FAtomicInteger() {
    }

    public FAtomicInteger(int initialValue) {
        value = initialValue;
    }

    // --------------主要方法--------------

    /**
     * 获取当前值
     *
     * @return 当前值
     */
    public final int get() {
        return value;
    }

    /**
     * 设置指定值
     *
     * @param newValue 新值
     */
    public final void set(int newValue) {
        value = newValue;
    }

    /**
     * 原子设置指定值并返回旧值
     *
     * @param newValue 新值
     * @return 旧值
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

    /**
     * 如果 当前值==expect，则以原子方式设置给定新值
     *
     * @param expect 预期值
     * @param update 新价值
     * @return ture 设置成功，反之 false
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * 以原子的方式增加 1
     *
     * @return 旧值
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

    /**
     * 以原子的方式减少 1
     *
     * @return 旧值
     */
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }

    /**
     * 以原子的方法将给定值添加到当前值
     *
     * @param delta 增量
     * @return 旧值
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

    /**
     * 以原子方式增加 1
     *
     * @return 新值
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

    /**
     * 以原子方式减少 1
     *
     * @return 新值
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }

    /**
     * 以原子方式将给定值添加到当前值
     *
     * @param delta 增量
     * @return 新值
     */
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

    // --------------进阶方法--------------

    /**
     * 以原子方式配合运算函数更新值
     *
     * @param unaryOperator 运算函数
     * @return 旧值
     */
    public final int getAndUpdate(IntUnaryOperator unaryOperator) {
        int prev, next;
        do {
            prev = get();
            next = unaryOperator.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }


    // --------------非核心方法--------------

    @Override
    public int intValue() {
        return get();
    }

    @Override
    public long longValue() {
        return get();
    }

    @Override
    public float floatValue() {
        return get();
    }

    @Override
    public double doubleValue() {
        return get();
    }
}
